package com.canyou.common;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.canyou.api.ResponseBO;
import com.canyou.system.model.Dept;
import com.canyou.system.model.OauthClient;
import com.canyou.system.service.OauthClientService;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import static com.canyou.api.ResponseBO.*;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author canyou
 * @since 2019-05-14
 */
@Api(tags = "登录处理")
@ApiSort(1000)
@RestController
@RequestMapping("/login")
public class LoginController {

    @Autowired
    @Qualifier("consumerTokenServices")
    private ConsumerTokenServices consumerTokenServices;

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private OauthClientService oauthClientService;

    @ApiOperation(value = "注销退出")
    @PostMapping(value = "/revoke_token")
    public ResponseBO revokeToken(HttpServletRequest request) {
        String accessToken = request.getHeader("Authorization");
        if (StrUtil.isBlank(accessToken)) {
            return illegal("用户未登录");
        }
        accessToken = accessToken.replaceAll("Bearer ", "");
        if (consumerTokenServices.revokeToken(accessToken)) {
            return ok("退出成功");
        } else {
            return fail("退出失败");
        }
    }

    @ApiOperation(value = "获取在线用户")
    @PostMapping(value = "/get_user_online")
    public ResponseBO getUserOnline() {
        List<OauthClient> clients = oauthClientService.list();
        List<Map<String, Object>> list = new ArrayList<>();
        for (OauthClient client : clients) {
            String clientId = client.getClientId();
            Collection<OAuth2AccessToken> tokens = tokenStore.findTokensByClientId(clientId);
            List<OAuth2AccessToken> tokenList = CollUtil.distinct(tokens);
            for (OAuth2AccessToken accessToken : tokenList) {
                OAuth2Authentication authentication = tokenStore.readAuthentication(accessToken);
                Map<String, Object> map = MapUtil.newHashMap(2);
                map.put("userName", authentication.getName());
                map.put("clientId", clientId);
                map.put("expiration", accessToken.getExpiration());
                list.add(map);
            }
        }
        return ok(list);
    }

    @ApiOperation(value = "踢出用户")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "clientId", paramType = "body", value = "客户端id",
                    dataType = "string", required = true, example = "1"),
            @ApiImplicitParam(name = "userName", paramType = "body", value = "用户名",
                    dataType = "string", required = true, example = "1")
    })
    @PreAuthorize("hasPerm('kick_out_user')")
    @GetMapping("/kick_out_user")
    public ResponseBO<Dept> kickOutUser(@RequestParam String clientId, @RequestParam String userName) {
        Collection<OAuth2AccessToken> tokens = tokenStore.findTokensByClientIdAndUserName(clientId, userName);
        for (OAuth2AccessToken accessToken : tokens) {
            if (accessToken.getRefreshToken() != null) {
                tokenStore.removeRefreshToken(accessToken.getRefreshToken());
            }
            tokenStore.removeAccessToken(accessToken);
        }
        return ok("踢出用户成功");
    }
}
